package com.example.tbplus14.Test;



import java.lang.invoke.*;
import java.lang.reflect.Constructor;
import java.math.BigDecimal;
import java.util.function.Supplier;

public class FactoryGenerator {

    public static <T> T createFactory(Class<T> factoryInterface, Class<?> targetClass, Class<?>... paramTypes) throws Throwable {
        MethodHandles.Lookup lookup = MethodHandles.lookup();

        // 获取构造器
        Constructor<?> constructor = targetClass.getDeclaredConstructor(paramTypes);
        MethodHandle constructorHandle = lookup.unreflectConstructor(constructor);

        // 生成方法类型
        Class<?>[] erasedParams = new Class[paramTypes.length];
        for (int i = 0; i < paramTypes.length; i++) {
            erasedParams[i] = Object.class;
        }

        MethodType samMethodType = MethodType.methodType(targetClass, erasedParams);
        MethodType instantiatedMethodType = MethodType.methodType(targetClass, paramTypes);

        // 创建工厂
        CallSite callSite = LambdaMetafactory.metafactory(
                lookup,
                "create", // 假设函数式接口的方法名为"apply"
                MethodType.methodType(factoryInterface),
                samMethodType,
                constructorHandle,
                instantiatedMethodType
        );

        return (T) callSite.getTarget().invoke();
    }

    // 支持通过类路径创建工厂
    public static <T> T createFactory(Class<T> factoryInterface, String className, Class<?>... paramTypes) throws Throwable {
        // 加载类
        Class<?> targetClass = Class.forName(className);
        return createFactory(factoryInterface, targetClass, paramTypes);
    }

    /**
     * 创建通用对象工厂（无参构造器）
     * @param targetClass 目标类
     * @param <T> 目标类类型
     * @return 工厂实例（通过 Supplier 接口获取对象）
     */
    public static <T> Supplier<T> createFactory(Class<T> targetClass) throws Throwable {
        MethodHandles.Lookup lookup = MethodHandles.lookup();
        Constructor<T> constructor = targetClass.getDeclaredConstructor();
        constructor.setAccessible(true); // 允许访问非公共构造器
        MethodHandle constructorHandle = lookup.unreflectConstructor(constructor);

        // 使用标准函数式接口 Supplier<T>
        CallSite callSite = LambdaMetafactory.metafactory(
                lookup,
                "get", // Supplier 接口的方法名
                MethodType.methodType(Supplier.class),
                MethodType.methodType(Object.class), // Supplier.get() 返回 T
                constructorHandle,
                MethodType.methodType(targetClass)
        );

        return (Supplier<T>) callSite.getTarget().invoke();
    }

    public static void main(String[] args) throws Throwable{
        ProdFactory factory = createFactory(ProdFactory.class, Prod.class);
        Prod prod = factory.create();
        prod.sumProdPrice(11, new BigDecimal("33"));
        prod.sumProdPrice();

        ProdFactory factoryStr = createFactory(ProdFactory.class, "com.example.tbplus14.Test.Prod");
        Prod prod1 = factoryStr.create();
        prod1.sumProdPrice(11, new BigDecimal("33"));
        prod1.sumProdPrice();

        Supplier<Prod> factorys = createFactory(Prod.class);
        Prod prods = factorys.get();
        prods.sumProdPrice(11, new BigDecimal("33"));
    }




}
@FunctionalInterface
interface ProdFactory {
    Prod create();
}


